/*
--------------------------------------------------------------------------------
				Ak-Lib. 
			 Project       	: Ak-Lib
			 Group         	: Ak-Lib R&D Team
			 Author        	: Ocean.Wang
			 Create Date 	: 05-01-2010
--------------------------------------------------------------------------------
Code Name 	:  A.K 	~v~
Description	:  Yet Another Cross-Platform Lib.
Cautions    	:
--------------------------------------------------------------------------------
Change History:
Version		: 0.1
Building 		: 05/01/10
10-05.01 first draft, build, debug and test.
--------------------------------------------------------------------------------
*/

#ifndef _INC_AK_STEP_
#define	_INC_AK_STEP_

#include "ak_types.h"
#include "ak_queue.h"
#include "ak_mem.h"
#include "ak_timer.h"
#include "ak_gears.h"
#include "ak_obj.h"

#ifdef __cplusplus
extern "C" {
#endif

/* Proc Ret */
#define STEP_RET_FAIL 	-1
#define STEP_RET_SUCC 	0
#define STEP_RET_WAIT 	1
#define STEP_RET_UNK 	2		/* By Pass, Not Proc */

/* Proc State */
#define STEP_ST_IDLE	0
#define STEP_ST_PROC	1
#define STEP_ST_FINI	2
#define STEP_ST_UNK		3

/* Proc Fini Indicator */
#define SPROC_SUCC		0
#define SPROC_FAIL		-1

/* Proc OP */
#define STEP_OP_DO 			0X01
#define STEP_OP_UNDO 		0X02
#define STEP_OP_BLOCK		0X03
#define STEP_OP_UNBLOCK		0X04
#define STEP_OP_TIMEOUT		0X05
#define STEP_OP_EVTHDL		0X06
#define STEP_OP_TEMINATE 	0X07


typedef struct{
	int 	toDur;			/* Timeout Dur, Based on ms. 0: No Timeout */
	int 	(*Do)();		/* The Step's Job Process */
	int 	(*Undo)();		/* If Fail, Term, Roll back */
	int 	(*EvtHdl)();	/* Event Handle */
	int		(*TimeOut)();	/* TimeOut Handle */
}_t_sStepDesc;


#define 	SPROC_MAX_ID 	1023
typedef struct{
	unsigned int 		id;				/* For Statistics */
	int 				total;	
	_t_sStepDesc 	** 	ppDesc;		/* The Step Desc Array */
	int 				(*Init)();
	int 				(*Fini)();
	int					(*Exception)();	/* The Exception Handle */
}_t_sProcDesc;


/* -----------------------------------------------------------------------------
** Add the Support 4: Statistic 
*/

typedef struct{
	unsigned int		avgDur;
	unsigned int		minDur;
	unsigned int		maxDur;
	unsigned long		total;
	unsigned long long	sumDur;
}_t_sStepDur;

typedef struct{
	/* Time Cost */
	_t_sStepDur 			succ;
	_t_sStepDur				fail;

	unsigned long 			block;
	unsigned long 			unblock;
	unsigned long 			terminate;
	unsigned long 			timeout;
}_t_sStepStat;

typedef struct{
	_t_sStepStat 	sstat[SPROC_MAX_ID + 1];
}_t_sProcStat;


#define 	SPROC_STAT_CLEAR(pStat) 	SYS_MEMZERO(pStat, sizeof(_t_sProcStat))

/* Add the Support 4:  Proc Allocation Pool */
typedef struct	{
	/* Heap & Pool */
	_t_sysMHeap 	mHeap;
	_t_sysMPool 	mPool;
	
	/* Slots:  */
	_t_sysMSlot 	mSlot;
}_t_sProcPool;


/* Proc Priority */
#define 	SPROC_PRI_HIGH 			0
#define 	SPROC_PRI_MEDI			1
#define 	SPROC_PRI_LOW 			2		

#define 	SPROC_PRI_MAX 			3

typedef struct{
	_t_sProcStat 		* 	pStat;
	_t_sProcPool		*	pPool;
	STimer_Svr 	 		* 	pTSvr;
	/* Priority Que */
	_t_sysCS				lock;
	_t_blist 				priQue[SPROC_PRI_MAX]; /* Only the Higher Priority Has all Proceed, will Process the Next Prority */
	
}_t_sProcSche;


/* -----------------------------------------------------------------------------
** The Process Context 
*/
/* Add Reserv Field for User, Such as Transaction ID. */
typedef struct _t_sProcUser{
	int 		iRes[4];	/* For User Rem the Integer ID */
	void  * 	pRes;		/* For User Rem the Memory Pointer */
}_t_sProcUser;


typedef struct _t_sProcNode{
	_t_bnode 				sNode; 	
	_t_sProcSche 		* 	pSche;
	STimer_Node 			tNode;	/* Timer */

	int 					priority;
	int 					bState;
	int 					bBlock;
	/* The Step Process */	
	_t_sProcDesc 		* 	pDesc;
	int 					step;	/* Current Step */
	void 				* 	pArg;	/* The Arg Param for the Step */

	_t_mTiming				timing;

	/* User Custom Field */
	_t_sProcUser 			user;
}_t_sProcNode;


extern	int 	SStep_SetTraceLvl(int lvl);
extern	int 	SStep_GetTraceLvl(void);

/* -----------------------------------------------------------------------------
** The Process Procedure 
*/
extern	int 			SProcPool_Init(_t_sProcPool * pPool, unsigned int count);

/* -----------------------------------------------------------------------------
** The Procedure  Schedule
*/
extern	int 	SProcSche_Init(_t_sProcSche * pSche, _t_sProcPool * pPool, STimer_Svr * pTSvr, _t_sProcStat * pStat);

/* The fChk is Used by User to Judge if the ProcNode is Really Wanted !
** if fChk != NULL, will be Called as fChk(pProcNode), Ret = 0, will be Term, Ret = -1, will be Bypass.
** if fChk == NULL, all found ID will be Term.
*/
extern	int 	SProcSche_TermByID(_t_sProcSche * pSche, unsigned int procID, int (*fChk)());
extern	int 	SProcSche_TermByMask(_t_sProcSche * pSche, unsigned int procMask, int (*fChk)());
extern	int 	SProcSche_TermAll(_t_sProcSche * pSche);

/* Return :  
** 0		: The Event is Processed. 	
** -1	: The Event is ByPass. 	
*/
extern	int 	SProcSche_EvtHdl(_t_sProcSche * pSche, void * pEvent);


/* -----------------------------------------------------------------------------
** The Procedure  Schedule
** When the Current Proc Success Fini. Go will return if the Postfix is Ready. 
** if(Post Add/Pre Add) has been Used. User should Mannually Check & Go! 
** (Because maybe the Postfix is not Block/Wait and Has alreay Concurrent Run with the Prefix Proc).
*/
extern	_t_sProcNode *	SProcNode_Init(_t_sProcSche *  pSche, _t_sProcDesc *	pDesc, void	* pArg, int priority);
extern	int 			SProcNode_Go(_t_sProcSche *  pSche, _t_sProcNode * pProc, int bOP, void * pEvent);

#ifdef __cplusplus
}
#endif

#endif




